display-name: "Games/Commander Keen Dreams"
meta: {"Working": ["All images", "Levels (no objects yet)", "Audio"]}

offsets:
{
	175424:     	{"version": "1.0",		"header-offset": 0x1B010, "huffman-offset": 0x29B88, "map-header-offset": 122688, "map-dict-offset": 171912, "audio-header-offset": 134512, "audio-dict-offset": 172932}, 
	213424:		{"version": "1.01 Shareware",	"header-offset": 0x1E6E0, "huffman-offset": 0x2B3D6, "map-header-offset": 124640, "map-dict-offset": 178134, "audio-header-offset": 148544, "audio-dict-offset": 179154}, 
	213536:		{"version": "1.13 Shareware",	"header-offset": 0x1E720,"huffman-offset":  0x2B446, "map-header-offset": 136784, "map-dict-offset": 178246, "audio-header-offset": 148608, "audio-dict-offset": 179266},
	212272:		{"version": "1.92 REV 0",	"header-offset": 0x1D760,"huffman-offset":  0x2B01E, "map-header-offset": 132752, "map-dict-offset": 177182, "audio-header-offset": 144576, "audio-dict-offset": 178202},
	213200:		{"version": "1.93 REV 1",	"header-offset": 0x1D830,"huffman-offset":  0x2B3BE, "map-header-offset": 132960, "map-dict-offset": 178110, "audio-header-offset": 144784, "audio-dict-offset": 179130},
	214912:		{"version": "1.20", 		"header-offset": 0x1DC10,"huffman-offset": 0x2BA70, "map-header-offset": 133952, "map-dict-offset": 179824, "audio-header-offset": 145776, "audio-dict-offset": 180844}
}

if ((file.name == "kdreams.ega") or (file.name == "egagraph.kdr"))
{
	//work out where things in the exe are, and link in the Huffman decompression table
	from "kdreams.exe"
	{
		header-offset: offsets[file.size].header-offset
		huffman-offset: offsets[file.size].huffman-offset

		at huffman-offset:
		unsigned16[512] huff-table
	}

	//link in the header, stored in the exe
	bitmap-count: 0
	masked-bitmap-count: 0
	sprite-count: 0

	packed-name: file.name

	from "kdreams.exe" at header-offset
	{
		file[1]
		{
			name: "Bitmaps header"
			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size
				bitmap-count = decompressed-size / 4				
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}
	
		file[1] 
		{
			name: "Masked Bitmaps header"
			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size
				masked-bitmap-count = decompressed-size / 4				
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}

		file[1]
		{
			name: "Sprites header"
			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size
				sprite-count = decompressed-size / 18				
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}

		file[1]: i
		{
			name: "Font " + (i + 1)
			folder: "Fonts"
			
			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size			
			}

			offset: _offset + 4

			compressed "keen-huffman"

			interpret-as "keenengine-font"
		}

		file[bitmap-count]: i
		{
			name: "Bitmap " + (i + 1)
			bitmap-number: i

			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size			
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}

		file[masked-bitmap-count]: i
		{
			name: "Masked Bitmap " + (i + 1)
			bitmap-number: i

			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size			
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}

		file[sprite-count]: i
		{
			name: "Sprite " + (i + 1)
			bitmap-number: i

			unsigned32 _offset			

			from packed-name at _offset
			{
				unsigned32 decompressed-size			
			}

			offset: _offset + 4

			compressed "keen-huffman"
		}

		file[1]
		{
			name: "Unmasked 8x8 tiles"
			unsigned32 offset

			decompressed-size: 104 * 8 * 4
			
			compressed "keen-huffman"

			interpret-as "keenengine-unmasked8x8"
		}

		file[1]
		{
			name: "Masked 8x8 tiles"
			unsigned32 offset

			decompressed-size: 20 * 8 * 5
			
			compressed "keen-huffman"

			interpret-as "keenengine-masked8x8"
		}

		skips: 0

		file[1]
		{
			name: "Unmasked 16x16 tiles"

			offset: 0			

			loop
			{
				unsigned32 read_offset
				offset = read_offset
				skips = skips + 1				
			} while (read_offset == 0xFFFFFFFF)
		}

		data((1440 - skips) * 4) tile-offsets //unmasked 16x16 offsets

		skips = 0

		file[1]
		{
			name: "Masked 16x16 tiles"

			offset: 0

			loop
			{
				unsigned32 read_offset
				offset = read_offset
				skips = skips + 1	

			} while (read_offset == 0xFFFFFFFF)	
				
		}
	}
}

alpha-mask: 1

if (file.name like "Bitmap *")
{
	from "Bitmaps header" at (bitmap-number * 4)
	{
		unsigned16 width-in-bytes
		unsigned16 height
	}

	image
	{	
		format: "I4"
		width: width-in-bytes * 8
		bit-stride: width * height
	}
}

if (file.name like "Masked Bitmap *")
{
	from "Masked Bitmaps header" at (bitmap-number * 4)
	{
		unsigned16 width-in-bytes
		unsigned16 height
	}

	image
	{	
		format: "A1I4"
		width: width-in-bytes * 8
		bit-stride: width * height
	}
}

if (file.name like "Sprite *")
{
	folder: "Sprites"

	from "Sprites header" at (bitmap-number * 18)
	{
		unsigned16 width-in-bytes
		unsigned16 height
		signed16 OrgX
		signed16 OrgY
		signed16 Rx1
		signed16 Ry1
		signed16 Rx2
		signed16 Ry2
		unsigned16 Shifts
	}

	image 
	{		
		format: "A1I4"
		width: width-in-bytes * 8
		bit-stride: width * height
	}
}

if (file.name == "unmasked 16x16 tiles")
{
	from "kdreams.exe" at (header-offset + (6 * 4) + (bitmap-count * 4) + (masked-bitmap-count * 4) + (sprite-count * 4))
	{
		unsigned32[1440] offsets
	}
	current-tile: 0

	image-layout-width: 288
	image-layout
	{
		loop (1440)
		{
			offset-to-image: offsets[current-tile]		

			if (offset-to-image != 0xFFFFFFFF)
			{
				at offset-to-image - offset:

				decompressed-size: 128
		
				compressed [file.remaining-bytes] "keen-huffman"
				{
					image
					{
						format: "I4"
						width: 16
						height: 16
						bit-stride: width * height
					}
				}
			}
			else
			{
				image
				{
					format: "Blank"
					width: 16
					height: 16
				}
			}
		
			current-tile = current-tile + 1
		}
	}
}


if (file.name == "masked 16x16 tiles")
{
	from "kdreams.exe" at (header-offset + (6 * 4) + (bitmap-count * 4) + (masked-bitmap-count * 4) + (sprite-count * 4) + (1440 * 4)) 
	{
		unsigned32[1206] offsets
	}
	current-tile: 0

	image-layout-width: 288
	image-layout
	{
		loop (1206)
		{
			offset-to-image: offsets[current-tile]

			if (offset-to-image != 0xFFFFFFFF)
			{
				at offset-to-image - offset:

				decompressed-size: 160
				compressed [file.remaining-bytes] "keen-huffman"
				{
					image
					{
						format: "A1I4"
						width: 16
						height: 16
						bit-stride: width * height
					}
				}

			} 
			else
			{
				image
				{
					format: "Blank"
					width: 16
					height: 16
				}
			}
			current-tile = current-tile + 1
		}
	}
}

if (file.name like ["kdreams.map", "gamemaps.kdr"])
{
	packed-name: file.name
	packed-size: file.size

	level-graphics-name: "kdreams.ega"
	if (!exists("kdreams.ega"))
	{
		level-graphics-name = "egagraph.kdr"
	}

	from "kdreams.exe"
	{
		this-version-data: offsets[file.size]

		at this-version-data.map-dict-offset:
		unsigned16[512] huff-table
	}

	from "kdreams.exe" at (this-version-data.map-header-offset + 2)
	{
		unsigned32[100] offsets
		valid-offsets: []
		valid-count: 0

		loop (100): i
		{
			if (offsets[i] != 0)
			{
				valid-offsets[valid-count] = offsets[i]
				valid-count = valid-count + 1
			}
		}

		valid-offsets[valid-count] = packed-size

		loop (valid-count - 1): i
		{
			file[1]
			{
				offset: 0
				size: packed-size

				from packed-name at valid-offsets[i]
				{
					decompressed-size: 42
					compressed[valid-offsets[i + 1] - valid-offsets[i]] "keen-huffman"
					{
						unsigned32[3] planeOffsets
						unsigned16[3] planeSizes
						unsigned16 width
						unsigned16 height
						fixed-string(16) name
						fixed-string(4) signature //!ID!

						interpret-as "kdreams-level"
					}
				}
			}
		}
	}
}

object-images: {
	1: {"name": "2", "y": -16},
	2: {"name": "10", "y": -16},
	3: "",
	4: "",
	5: "",
	6: "",
	7: "",
	9: "",
	11: "",
	12: "",
	14: "",
	16: "",
	17: "",
	18: "",
	19: "",
	21: "103",
	22: "105",
	23: "107",
	24: "109",
	25: "111",
	26: "113",
	27: "115",
	28: "116",
	29: "93",
	30: {"name": "121", "y": -8 },
	31: "123",
	32: "128",
	33: "141",
	41: {"name": "179", "y": -16},
	42: "189",
	43: {"name": "196", "y": -16 },
	45: "205",
	46: "209",
	47: {"name": "211", "y": -16 },
	48: "223",
	49: {"name": "225", "y": -16 },
	50: "241",
	51: "239",
	52: "243",
	57: {"name": "251", "y": -16 },
	59: {"name": "275", "y": -16 },
	61: {"name": "289", "y": -88 }
}

file-format kdreams-level
{
	from "kdreams.exe"
	{
		this-version-data: offsets[file.size]

		at this-version-data.map-dict-offset:
		unsigned16[512] huff-table
	}

	level
	{
		grid-x: 16
		grid-y: 16

		at planeOffsets[0] :
		unsigned16 sizeAfterDecarmack

		decompressed-size: sizeAfterDecarmack
		compressed [planeSizes[0]] "keen-huffman"
		{
			unsigned16 decompressedSize
			magic-number: 0xABCD
			compressed [sizeAfterDecarmack - 2] "KeenRLE"
			{
				level-layer
				{
					data-type: "unsigned16"
					layer-name: "Background"
					layer-image: level-graphics-name + "\\Unmasked 16x16 tiles"
					order: 0
				}
			}
		}

		at planeOffsets[1] :
		unsigned16 sizeAfterDecarmack

		decompressed-size: sizeAfterDecarmack
		compressed [planeSizes[1]] "keen-huffman"
		{
			unsigned16 decompressedSize
			magic-number: 0xABCD
			compressed [sizeAfterDecarmack - 2] "KeenRLE"
			{
				level-layer
				{
					data-type: "unsigned16"
					layer-name: "Foreground"
					layer-image: level-graphics-name + "\\Masked 16x16 tiles"
					order: 1
					ignore-tile: 0
				}
			}
		}

		at planeOffsets[2] :
		unsigned16 sizeAfterDecarmack

		decompressed-size: sizeAfterDecarmack
		compressed [planeSizes[1]] "keen-huffman"
		{
			unsigned16 decompressedSize
			magic-number: 0xABCD
			compressed [sizeAfterDecarmack - 2] "KeenRLE"
			{
				level-layer
				{
					data-type: "unsigned16"
					layer-name: "Objects"
					layer-images-prefix: level-graphics-name + "\\sprite "
					layer-images: object-images
					order: 1
					ignore-tile: 0
				}
			}
		}
	}
}

if ((file.name == "kdreams.aud") or (file.name == "audio.kdr")) {
	packed-name: file.name
	from "kdreams.exe"
	{
		this-version-data: offsets[file.size]

		at this-version-data.audio-header-offset:
		unsigned32[85] audio-offsets

		at this-version-data.audio-dict-offset:
		unsigned16[512] huff-table
	} 

	file[85]: i
	{
		name: "Audio " + i
		offset: audio-offsets[i]

		skip-if ((offset == 0) or (offset >= file.size))			

		from packed-name at offset
		{
			unsigned32 decompressed-size			
		}

		offset = offset + 4
		compressed "keen-huffman"

		interpret-as "sound-PC-APOGEE-AUDIOT"
	}
}